﻿/**
 *	\file		lxpref_route_clt_usr.cxx
 *	\date		(2014-12-19 11:28:27)/(2014-12-19 11:28:27)
 *-----------------------------------------------------------------------------
 *	\brief
 *	\version	1.0.0.1
 *	\author		Nick Shallery	(nicknide@gmail.com)
 *	\copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#include	"./lxpref_route_clt_usr.hxx"

#include	"./lxpref_route.hxx"

#include	"./lxpref_route_msg.hxx"

#include	"../lxsamsara/recurrence.h"
#include	"../lxsamsara/dream.h"

#include	<lolix/toy/stdc_fun.h>
#include	<lolix/loli/file.h>

#include	<lolix/toy/archive.hpp>
#define		LOLIX_DEF__MEMORY_FILE_STREAM
#include	<lolix/toy/archive_file_filter.hpp>


lxpref::_inst::clt_usr::clt_usr(lolix::dynamic_allocator* alc)
	: _net_dat(alc)
	, _dat_cnt(0)
{
}


lxpref::_inst::clt_usr::~clt_usr(void)
{
	_recur->release();
	_fasync->safe_release();
	_stdc->release();
	_alc->release();
}


lolix::LOLIX_RETNV
lxpref::_inst::clt_usr::create_inst(this_type** out_ptr
	, lolix::dynamic_allocator* alc
	, lolix::ref_factory* ref_fac
	, lolix::toy::stdc_fun* stdc
	, lolix::loli::file_async* fasync
	, lxsamsara::recurrence* recur
)
{
	LOLIX_RETNV rtv;
	this_type* ptr;
	if ( LOLIX_CHECK_ERROR(rtv = __Create_inst_set_alc(&ptr, alc, ref_fac, alc)) )
		return rtv;
	(ptr->_stdc = stdc)->inc_ref();
	(ptr->_fasync = fasync)->inc_ref();
	(ptr->_recur = recur)->inc_ref();
	*out_ptr = ptr;
	return rtv;
}


lolix::loli::file_async*
lxpref::_inst::clt_usr::_get_file_async(void)const
{
	return _fasync;
}


void
lxpref::_inst::clt_usr::_get_recv_buf(void** out_buf, size_type* buf_size)
{
	if ( _net_dat.size() < this->_dat_cnt + 512 )
		_net_dat.resize(_net_dat.size() + KB(1));
	*out_buf = &_net_dat.front() + this->_dat_cnt;
	*buf_size = _net_dat.size() - this->_dat_cnt;
}


void
lxpref::_inst::clt_usr::_do_recv(lolix::size_type datLen, Fn_OnRecvMsg onRecvMsg, void* usr_ptr)
{
	lolix::loli::memory_file_stream<allocator_type> mfs(this->_stdc, this->_alc);
	this->_dat_cnt += datLen;
	mfs.swap_datas(this->_net_dat, this->_dat_cnt);
	mfs.seek_to(0);

	lolix::lx_i64 cur_pos = 0;

	lxsamsara::dream* dr;
	lolix::LOLIX_RETNV rtv;
	if ( LOLIX_CHECK_ERROR(rtv = this->_recur->nap(&dr)) )
		return;
	atexit_release(*dr);

	if ( rtv != lolix::LOLIX_INFO_REOPERATOR )
	{
		message::packet_header<allocator_type> pheader(this->_alc);
		lolix::toy::archive_no_throw arc(&mfs);

		auto& eh = arc.get_eh();
		auto ivk_awaken_dream(eh.push_member(dr, &lxsamsara::dream::awaken_this));
		do
		{
			arc >> pheader;
			if ( pheader.dat.empty() )
				onRecvMsg(this, pheader.msg_type, 0, 0, usr_ptr);
			else
				onRecvMsg(this, pheader.msg_type, &pheader.dat.front(), pheader.dat.size(), usr_ptr);
			cur_pos = 0;
			mfs.seek((lolix::lx_i64*)&cur_pos, 1);
		} while ( mfs.size() != cur_pos );
	}

	lolix::size_type used = static_cast<lolix::size_type>(cur_pos);
	mfs.swap_datas(this->_net_dat, 0);
	this->_net_dat.erase(this->_net_dat.begin(), this->_net_dat.begin() + used);
	this->_dat_cnt -= used;
}

